#ifndef __MCS__FUNCTION_FACTORY__HPP
#define __MCS__FUNCTION_FACTORY__HPP

#include "Function.hpp"
#include "FunctionSignature.hpp"
#include "FunctionFactoryDetails.hpp"

class FunctionFactory : public Object
{
public:
	FunctionFactory() : Object() {}
	~FunctionFactory() {}

	ptr<Function> getFunction(FunctionSignature const & signature) const
	{
		FunctionsDatabase::const_iterator it = database_.find(signature);
		if(it == database_.end()) return ptr<Function>();
		return it->second;
	}

	void insertFunction(ptr<Function> const & func)
	{
		assert(database_.count(func->signature()) == 0);
		database_.insert(std::make_pair(func->signature(), func));
	}
	
	template<class T> void insertFunction(String const & name, T pFunc)
	{
		insertFunction(new FunctionT<T>(name, pFunc));
	}
private:
	typedef std::map<FunctionSignature, ptr<Function> > FunctionsDatabase;
	FunctionsDatabase database_;
};

class FunctionCollection
{
public:
	static void registerCollections(FunctionFactory * factory)
	{
		FunctionCollection * coll = head;
		while(coll)
		{
			coll->registerFunctions(factory);
			coll = coll->next_;
		}
	}

	FunctionCollection() { next_ = head; head = this; }
	virtual ~FunctionCollection() { assert(head == this); head = next_; }

	virtual void registerFunctions(FunctionFactory * factory) = 0;
private:
	static FunctionCollection * head;
	FunctionCollection * next_;
};

#endif //__MCS__FUNCTION_FACTORY__HPP
